這個檔案建立一個 express obj
( 習慣命名為 app
, 也比較方便 ), 還有一些 middleware 有關及其他的設定, 來 export module 。 下方節錄出來的一些 code 就在處理上述的任務
var express = require('express');
var app = express();
...
module.exports = app;
回到 www 進入點檔案 ( 上一篇文章提到的 ) , 這裡就是 export
的來源
現在來仔細瞧瞧 app.js
。 首先用 require()
來 import
一些 libraries , 大部分上篇文章都提到了, 其中有一個 path
, 用來解析檔案路徑
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
接著我們從 routes 目錄 require()
modules ( 目前一樣還是在討論 app.js
這支檔案喔~ ):
我們會新增檔案來處理書本相關的 routes , 這時就會擴充這個 app 的 skeleton
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
Note: 這時我們 import module, 但我們實際上還沒用到 routes ( 下方文章會討論 )
一堆 require()
之後, 用 express module 建立 app obj
, 然後設定 view engine ,這邊有兩步。
首先設定 views
值, 指定存放 templates 的資料夾 ( 這裡是 /views
) ; 接著設定 view engine
值, 指定 template library ( 這裡是 pug
)
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
再來設定置入 req handling chain 的 mw libraries , 使用 app.use()
。 這些第三方 libraries 在前面就有 import 了, 此外我們還用 express.static
mw 來使 Express 乘載放在 /public 的靜態檔案
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
現在, 其他的 mw 也準備就緒, 我們要來新增 route-handling
到 req handling chain:
app.use('/', indexRouter);
app.use('/users', usersRouter);
Note: 上方我們所指定的 ( /
& /users
) , 都帶有前綴去定義 routes 。 如果有個 /profile
被 users
module 拿來 import 定義成為一個 route , 那麼要這樣存取: /users/profile
。 後續會有更多的討論
最後的 mw 新增一些回應 err & 404 的處理
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
現在 Express app obj 全部設定完畢, 最後的步驟就是 exports ( 這樣做允許 app.js
被 /bin/www
import )
以下是 /routes/users.js
( route 檔案架構都很相似, 這裡略過 /routes/index.js
) , 第一行我們很熟悉了, 第二行則是與先前不同 , 改成建立 express.Router
obj , 接著指定一個 route , 最後 export ( 這邊是要給 app.js
import , 跟上面的不同 )
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
這個 route 定義了一個 callback , 當 HTTP GET
req 偵測到 pattern 正確吻合 ( /users
( app.js 設定的 ) 加上 /
( 這邊設定的 ) , 也就是 /users/
) 就會被呼叫。
Note: 啟動 server 然後點看看 (http://localhost:3000/users/) , 我們應該會看到 'respond with a resource' 這段訊息 , 如果我們更改文字 ( 或加入 HTML tag ) 重啟 server 後重整瀏覽器 , 畫面也會跟著改變
值得一提的是: callback 含有第三個參數 next
, 且是個 mw function 而非簡單的 route callback 。 雖然這段 code 沒有現在使用 next
, 但之後如果要在 /
路徑增加多重 route 處理就有可能會用到
views templates 被存放在 /views 資料夾下, 副檔名為 .pug 。 Response.render()
是用來 render obj 內的變數到 template 上, 並傳遞結果作為 res 。 下方是 /routes/index.js
的 code, 可以看到 route render 一個名為 title 的變數到 index template 裡
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
與之相對應的 template ( index.pug
) 顯示如下。 我們將會在後續討論更多相關語法, 現在只要知道這個 title
變數被安插進指定 template 的行為就好
extends layout
block content
h1= title
p Welcome to #{title}
自我練習: 建立新 route /routes/users.js
, URL /users/cool/
的頁面要顯示 "You're so cool"
點選右邊連結看有沒有完成這項練習 (http://localhost:3000/users/cool/)
下一節, 要來改動 skeleton, 讓它像一個圖書館網站